#include <iostream>

template <typename T>
class stack {
public:
    stack();
    stack(const stack<T>& obj);
    ~stack();

    stack<T>& operator=(const stack<T>& obj);

    void push(T val);
    void pop();
    bool empty();
    T top();
    void swap(stack<T>& obj);
    unsigned long size();

private:
    T* array;
    unsigned long idx;
    unsigned long length;

    void resize(unsigned long size);
};

template <typename T>
stack<T>::stack()
{
    array = new T(1);
    idx = 0;
    length = 1;
}

template <typename T>
stack<T>::stack(const stack<T>& obj)
{
    array = new T(obj.length);
    for(int i = 0; i < obj.idx; i++)
        array[i] = obj.array[i];
    idx = obj.idx;
    length = obj.length;
}

template <typename T>
stack<T>::~stack()
{
    delete array;
}

template <typename T>
stack<T>& stack<T>::operator=(const stack<T>& obj)
{
    if(this == &obj)
        return *this;
    if(array != NULL)
        delete array;
    array = new T(obj.length);
    for(int i = 0; i < obj.idx; i++)
        array[i] = obj.array[i];
    idx = obj.idx;
    length = obj.length;
    return *this;
}

template <typename T>
void stack<T>::push(T val)
{
    if(idx == length)
        resize(idx*2);
    else if(idx*4 <= length)
        resize(idx*2);
    array[idx] = val;
    idx += 1;
}

template <typename T>
void stack<T>::pop()
{
    idx -= 1;
}

template <typename T>
T stack<T>::top()
{
    return array[idx-1];
}

template <typename T>
bool stack<T>::empty()
{
    return idx == 0;
}

template <typename T>
unsigned long stack<T>::size()
{
    return idx;
}

template <typename T>
void stack<T>::resize(unsigned long size)
{
    T* tmp = new T(size);
    for(int i = 0; i < idx; i++)
        tmp[i] = array[i];
    delete array;
    array = tmp;
    length = size;
}

template <typename T>
void stack<T>::swap(stack<T>& obj)
{
    stack<T> tmp = obj;
    obj = *this;
    *this = tmp;
}

int main()
{
    stack<int> array;
    for(int i = 0; i < 5; i++)
        array.push(i);
    stack<int> array2;
    for(int i = 6; i < 8; i++)
        array2.push(i);
    array2.swap(array);

    std::cout << "size " << array2.size() << std::endl;
    while(!array2.empty())
    {
        std::cout << array2.top() << std::endl;
        array2.pop();
    }
    while(!array.empty())
    {
        std::cout << array.top() << std::endl;
        array.pop();
    }
    return 0;
}
